"""资产树项"""
import os

import bpy
from bpy.props import CollectionProperty, StringProperty, IntProperty, BoolProperty
from bpy.types import PropertyGroup

from . import asset_items
from .prefer import Preferences


class FolderTree(PropertyGroup, Preferences):
    """name
    资产文件夹树
    """

    @property
    def parent_path(self) -> str:
        return os.path.dirname(self.folder_path)

    @property
    def child_assets(self) -> 'list[asset_items.AssetItem]':
        """
        反回活动文件夹所有子项
        """
        return [item for item in self.active_assets if self.name in item.name]

    @property
    def pointer(self) -> 'TreePointer':
        return self.asset_tree_pointer_

    @property
    def trees(self) -> 'list[FolderTree]':
        """反回当前项所在的树"""
        return self.find_trees_(self.asset_type)

    @property
    def children_trees(self) -> 'list[FolderTree]':
        """反回当前树的所有子树
        就是所有子级
        """
        return [tree for tree in self.trees if self.folder_path in tree.parent_path]

    @property
    def child_trees(self) -> 'list[FolderTree]':
        """反回子树"""
        return [tree for tree in self.trees if tree.parent_path == self.folder_path]

    @property
    def parent(self):
        """
        反回父树项
        """
        return self.active_trees.get(self.parent_path)

    @property
    def folder_name(self) -> str:
        """反回文件夹名称"""
        if self.folder_path:
            return os.path.basename(self.folder_path)

    is_show: BoolProperty(name='是否显示',
                          default=True,
                          )

    @property
    def trees(self) -> 'list[FolderTree]':
        """反回当前项所在的树"""
        key = self.tree_asset_key_(self.asset_type)
        return getattr(self.asset_tree_pointer_, key)

    # parent and child
    level: IntProperty(name='资产级数，用于显示文件夹子级的缩进', min=0)

    def set_show(self, tree):
        """设置显示值
        在更新文件夹的显示布尔值时更新子资产的显示属性
        """
        if not self.show_child:
            tree.is_show = False  # 隐藏
        else:
            if tree.have_child_folder:
                tree.is_show = tree.parent.show_child  # 按父级的是否显示子级设置是否显示
            else:
                tree.is_show = tree.parent.is_show and tree.parent.show_child

    def update_show_child(self, context):
        """
        更新显示子级
        更改则设置子级目录的show属性
        折叠隐藏
        """
        for tree in self.active_trees:
            if (self.folder_path in tree.folder_path) and (self.folder_path != tree.folder_path):
                self.set_show(tree)

    show_child: BoolProperty(name='显示子级',
                             description='',
                             default=True,
                             update=update_show_child,
                             )

    have_child_asset: BoolProperty(name='是有子级的')
    have_child_folder: BoolProperty(name='是有子级文件夹的')

    def update_child_tree(self):
        """更新子树"""
        for tree in self.children_trees:
            # 设置当前树的所有子树选中状态,如果当前项为True，则所有子项都为True
            tree.selected = self.selected

    def update_selected(self, context):
        """更新文件夹下的所有子级选择状态
        如果父级不
        """
        pointer = self.asset_tree_pointer_
        if pointer.is_updating:  # 如果在更新中则跳过
            return
        try:
            pointer.is_updating = True
            for child in self.child_assets:
                child.selected = self.selected
            self.update_child_tree()

        finally:
            pointer.is_updating = False

    selected: BoolProperty(name='已选中',
                           update=update_selected,
                           )

    folder_path: StringProperty(subtype='DIR_PATH', name='文件夹路径')
    asset_type: StringProperty(name='资产的类型')


class TreePointer(PropertyGroup, Preferences):
    """树属性,保存了资产的文件夹树结构
    """

    asset_scene_tree: CollectionProperty(
        name='场景',
        type=FolderTree,
    )
    asset_object_tree: CollectionProperty(
        name='物体',
        type=FolderTree,
    )

    def update_index(self, context):
        """更新资产索引值"""
        for asset in self.active_assets:
            asset.is_show = self.active_tree.folder_path in asset.asset_path

    asset_object_index: IntProperty(
        update=update_index,
    )
    asset_scene_index: IntProperty(
        update=update_index,
    )

    def from_path_get_level(self, path: str) -> int:
        """通过输入路径来获取路径的目录级数
        比较根目录和输入目录之间的差异"""
        asset_path = self.pref.asset_root_path
        root_len = len(asset_path.split('\\'))
        path_len = len(path.split('\\'))
        level = path_len - root_len
        return level

    def add(self, path: str, category: str, have_child_folder: bool):
        """添加树项
        根据输入的类型,来决定添加到那一个项里面"""
        tree_key = self.tree_asset_key_(category)
        tree = getattr(self, tree_key)
        if path not in tree:
            new = tree.add()
            new.asset_type = category
            new.name = new.folder_path = path
            new.level = self.from_path_get_level(path)
            new.have_child_folder = have_child_folder


class_tuple = (
    FolderTree,
    TreePointer,
)

register_class, unregister_class = bpy.utils.register_classes_factory(
    class_tuple)


def register():
    register_class()


def unregister():
    unregister_class()
